package com.zhentao.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhentao.pojo.EmailVerification;
import com.zhentao.pojo.User;
import com.zhentao.service.EmailVerificationService;
import com.zhentao.service.UserService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;

@RestController
@RequestMapping("/auth")
public class LoginController {

    @Autowired
    private UserService usersService;


    @Autowired
    private EmailVerificationService emailVerificationService;

    @Autowired
    private org.springframework.mail.javamail.JavaMailSender mailSender;

    @org.springframework.beans.factory.annotation.Value("${spring.mail.username}")
    private String fromEmail;

    private final SecretKey jwtKey = Keys.hmacShaKeyFor("OceanBridge-SecretKey-Use-At-Least-256-bit-Length-For-HS256".getBytes(StandardCharsets.UTF_8));
    private final long accessTokenTtlMs = 60 * 60 * 1000; // 1 小时
    private final long refreshTokenTtlMs = 7L * 24 * 60 * 60 * 1000; // 7 天

    // 在这里添加 @PostConstruct 方法
    @PostConstruct
    public void init() {
        System.out.println("邮件配置 - fromEmail: " + fromEmail);
        System.out.println("mailSender: " + mailSender);
    }

    // 3.1 认证模块（骨架）

    @PostMapping("/register")
    public ResponseEntity<Map<String, Object>> register(@RequestBody RegisterRequest request) {
        Map<String, Object> body = new HashMap<>();

        // 邮箱和密码是必填的
        if (isBlank(request.email) || isBlank(request.password)) {
            return badRequest("邮箱和密码不能为空");
        }

        // 如果没有提供用户名，使用邮箱前缀作为用户名
        String username = request.username;
        if (isBlank(username)) {
            username = request.email.split("@")[0];
        }

        // 用户名/邮箱唯一性校验
        boolean existsUsername = usersService.count(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)) > 0;
        if (existsUsername) return badRequest("用户名已存在");

        boolean existsEmail = usersService.count(new LambdaQueryWrapper<User>()
                .eq(User::getEmail, request.email)) > 0;
        if (existsEmail) return badRequest("邮箱已注册");

        // 创建用户（密码使用 SHA-256 存储）
        User user = new User();
        user.setUsername(username);
        user.setEmail(request.email);
        user.setPassword(sha256(request.password));
        user.setNickname(username); // 设置昵称，默认使用用户名
        user.setStatus(1); // 默认启用
        user.setEmailVerified(0); // 默认未验证
        user.setSailorAuthStatus(0); // 默认未认证海员
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        usersService.save(user);

        // 创建邮箱验证码记录（占位逻辑：生成 6 位数字码并保存）
        String code = generateCode6();
        EmailVerification ev = new EmailVerification();
        ev.setUserId(user.getId());
        ev.setEmail(user.getEmail());
        ev.setCode(code);
        ev.setIsVerified(0);
        ev.setCreatedAt(new Date());
        emailVerificationService.save(ev);
        // 发送邮件验证码
        sendVerificationMail(request.email, code, "register");

        body.put("message", "注册成功，验证码已发送到邮箱，请查收");
        body.put("email", request.email);
        return ResponseEntity.ok(body);
    }

    @PostMapping("/verify-email")
    public ResponseEntity<Map<String, Object>> verifyEmail(@RequestBody VerifyEmailRequest request) {
        if (isBlank(request.email) || isBlank(request.code)) {
            return badRequest("参数不完整");
        }

        EmailVerification record = emailVerificationService.getOne(new LambdaQueryWrapper<EmailVerification>()
                .eq(EmailVerification::getEmail, request.email)
                .eq(EmailVerification::getCode, request.code)
                .orderByDesc(EmailVerification::getId)
                .last("limit 1"));

        if (record == null) return badRequest("验证码错误");
        if (Objects.equals(record.getIsVerified(), 1)) return badRequest("该邮箱已验证");

        record.setIsVerified(1);
        emailVerificationService.updateById(record);

        // 更新用户表的邮箱验证状态
        User user = usersService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, request.email));
        if (user != null) {
            user.setEmailVerified(1);
            user.setUpdateTime(new Date());
            usersService.updateById(user);
        }

        return ok("邮箱验证成功");
    }

    @PostMapping("/login")
    public ResponseEntity<Map<String, Object>> login(@RequestBody LoginRequest request) {
        if (isBlank(request.usernameOrEmail) || isBlank(request.password)) {
            return badRequest("参数不完整");
        }

        LambdaQueryWrapper<User> q = new LambdaQueryWrapper<>();
        q.eq(User::getUsername, request.usernameOrEmail).or()
                .eq(User::getEmail, request.usernameOrEmail);
        User user = usersService.getOne(q);
        if (user == null) return badRequest("用户不存在");

        if (!sha256(request.password).equals(Optional.ofNullable(user.getPassword()).orElse(""))) {
            return badRequest("密码错误");
        }

        // 校验邮箱是否已验证（若存在记录且未验证则阻止登录）
        EmailVerification latest = emailVerificationService.getOne(new LambdaQueryWrapper<EmailVerification>()
                .eq(EmailVerification::getEmail, user.getEmail())
                .orderByDesc(EmailVerification::getId)
                .last("limit 1"));
        if (latest != null && !Objects.equals(latest.getIsVerified(), 1)) {
            return badRequest("邮箱未验证，请先完成邮箱验证");
        }

        Map<String, Object> body = new HashMap<>();
        body.put("accessToken", generateJwt(user, accessTokenTtlMs));
        body.put("refreshToken", generateJwt(user, refreshTokenTtlMs));
        body.put("userId", user.getId());
        body.put("username", user.getUsername());
        return ResponseEntity.ok(body);
    }

    @PostMapping("/logout")
    public ResponseEntity<Map<String, Object>> logout() {
        Map<String, Object> body = new HashMap<>();
        body.put("message", "logout endpoint placeholder");
        return ResponseEntity.ok(body);
    }

    @PostMapping("/refresh")
    public ResponseEntity<Map<String, Object>> refresh(@RequestBody RefreshTokenRequest request) {
        if (isBlank(request.refreshToken)) return badRequest("参数不完整");
        Map<String, Object> body = new HashMap<>();
        // 简单校验：能解析即认为有效（生产需验证类型/黑名单/过期）
        try {
            Jwts.parserBuilder().setSigningKey(jwtKey).build().parseClaimsJws(request.refreshToken);
        } catch (Exception e) {
            return badRequest("refreshToken 无效");
        }
        body.put("accessToken", Jwts.builder()
                .setSubject("access")
                .setExpiration(new Date(System.currentTimeMillis() + accessTokenTtlMs))
                .signWith(jwtKey, SignatureAlgorithm.HS256)
                .compact());
        return ResponseEntity.ok(body);
    }

    @PostMapping("/password/forgot")
    public ResponseEntity<Map<String, Object>> forgotPassword(@RequestBody ForgotPasswordRequest request) {
        if (isBlank(request.email)) return badRequest("参数不完整");
        User user = usersService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, request.email));
        if (user == null) return badRequest("邮箱未注册");

        String code = generateCode6();
        EmailVerification ev = new EmailVerification();
        ev.setUserId(user.getId());
        ev.setEmail(user.getEmail());
        ev.setCode(code);
        ev.setIsVerified(0);
        ev.setCreatedAt(new Date());
        emailVerificationService.save(ev);
        // 发送邮件验证码
        sendVerificationMail(request.email, code, "forgotPassword");

        return ok("验证码已发送到邮箱，请查收");
    }

    @PostMapping("/password/reset")
    public ResponseEntity<Map<String, Object>> resetPassword(@RequestBody ResetPasswordRequest request) {
        if (isBlank(request.email) || isBlank(request.code) || isBlank(request.newPassword)) {
            return badRequest("参数不完整");
        }

        EmailVerification record = emailVerificationService.getOne(new LambdaQueryWrapper<EmailVerification>()
                .eq(EmailVerification::getEmail, request.email)
                .eq(EmailVerification::getCode, request.code)
                .orderByDesc(EmailVerification::getId)
                .last("limit 1"));
        if (record == null) return badRequest("验证码错误");

        User user = usersService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, request.email));
        if (user == null) return badRequest("用户不存在");

        user.setPassword(sha256(request.newPassword));
        user.setUpdateTime(new Date());
        usersService.updateById(user);

        record.setIsVerified(1);
        emailVerificationService.updateById(record);
        return ok("密码已重置");
    }

    @GetMapping("/profile")
    public ResponseEntity<Map<String, Object>> profile() {
        Map<String, Object> body = new HashMap<>();
        body.put("message", "profile endpoint placeholder");
        return ResponseEntity.ok(body);
    }

    // ===== 请求模型（为便于快速集成，放置为内部静态类）=====
    public static class RegisterRequest {
        public String email;
        public String password;
        public String username;
    }

    public static class VerifyEmailRequest {
        public String email;
        public String code;
    }

    public static class LoginRequest {
        public String usernameOrEmail;
        public String password;
    }

    public static class RefreshTokenRequest {
        public String refreshToken;
    }

    public static class ForgotPasswordRequest {
        public String email;
    }

    public static class ResetPasswordRequest {
        public String email;
        public String code;
        public String newPassword;
    }

    // ===== 内部工具方法 =====
    private boolean isBlank(String s) {
        return s == null || s.trim().isEmpty();
    }

    private String sha256(String raw) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(raw.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : hash) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("SHA-256 不可用", e);
        }
    }

    private String generateCode6() {
        int n = (int)(Math.random() * 1_000_000);
        return String.format("%06d", n);
    }

    private String generateJwt(User user, long ttlMs) {
        long now = System.currentTimeMillis();
        return Jwts.builder()
                .setSubject(String.valueOf(user.getId()))
                .claim("username", user.getUsername())
                .setIssuedAt(new Date(now))
                .setExpiration(new Date(now + ttlMs))
                .signWith(jwtKey, SignatureAlgorithm.HS256)
                .compact();
    }

    private ResponseEntity<Map<String, Object>> ok(String message) {
        Map<String, Object> body = new HashMap<>();
        body.put("message", message);
        return ResponseEntity.ok(body);
    }

    private ResponseEntity<Map<String, Object>> badRequest(String message) {
        Map<String, Object> body = new HashMap<>();
        body.put("message", message);
        return ResponseEntity.badRequest().body(body);
    }

    // 发送验证码邮件（纯文本）
    private void sendVerificationMail(String toEmail, String code, String scene) {
        System.out.println("开始发送邮件到: " + toEmail + ", 验证码: " + code); // 添加这行
        try {
            org.springframework.mail.SimpleMailMessage message = new org.springframework.mail.SimpleMailMessage();
            message.setFrom(fromEmail);
            message.setTo(toEmail);
            message.setSubject("OceanBridge - 邮箱验证");
            String body = String.format("场景：%s\n验证码：%s\n有效期：5分钟\n如非本人操作请忽略。", scene, code);
            message.setText(body);
            mailSender.send(message);
        } catch (Exception e) {
            // 发送失败不影响主流程，但记录错误日志便于排查
            System.err.println("邮件发送失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
